package model.inventory;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;

import model.Settings;
import model.contents.ContentType;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import util.LoggingUtils;
import util.PlayerUtilities;

public class InventoryDefinitionBuilder {
	public static final String MAIN_IMAGE_CONTAINER_STRING = "mainImageContainer";
	private InventoryDefinition definition;

	public InventoryDefinitionBuilder() {
		definition = InventoryDefinition.getInstance();
	}

	public InventoryDefinition buildFromCSV() {
		String fileName = Settings.INVENTORY_DEF_CSV;
		File inventoryDefinitionFile = new File(fileName);
		if (inventoryDefinitionFile.exists()) {
			List<String[]> inventorySettings = PlayerUtilities.getArrayFromCSVFile(fileName);
			applySettingsToInventoryDefinition(inventorySettings, definition);
		}
		return definition;
	}

	private void applySettingsToInventoryDefinition(List<String[]> inventorySettings, InventoryDefinition def) {
		String[] columnNames = inventorySettings.remove(0);
		for (int i = 0; i < inventorySettings.size(); i++) {
			String[] record = inventorySettings.get(i);
			applySetting(record, columnNames);
		}
	}

	private void applySetting(String[] record, String[] columnNames) {
		try {
			int typeColumn = getFieldIndex(columnNames, "type");
			String type = record[typeColumn];
			String field = record[getFieldColumnIndex(columnNames)];
			String format = record[getFieldIndex(columnNames, "format")];
			JSONParser parser = new JSONParser();
			// System.out.println(type + " " + field + " " + format);
			if (type.equals("image")) {
				String containerIdString = record[getFieldIndex(columnNames, "container_id")];
				int id = Integer.parseInt(containerIdString);
				definition.addFieldMapping(field, ContentType.IMAGE, id);
			} else if (type.equals("mapping")) {
				String containerIdString = record[getFieldIndex(columnNames, "container_id")];
				int id = Integer.parseInt(containerIdString);
				definition.addFieldMapping(field, ContentType.TEXT, id);
				definition.addTextFormatMapping(field, (JSONObject) parser.parse(format));
				// TODO : add formatting for text labels here
			} else if (type.equals("table_field")) {
				definition.addTableFieldFormat(field, (JSONObject) parser.parse(format));
			} else if (type.equals("boxType")) {
				if (format.equalsIgnoreCase("autobox")) {
					definition.setBoxType(InventoryDefinition.BoxType.AUTOBOX);
				} else {
					definition.setBoxType(InventoryDefinition.BoxType.REALESTATEBOX);
				}
			} else if (type.equals(MAIN_IMAGE_CONTAINER_STRING)) {
				String containerIdString = record[getFieldIndex(columnNames, "container_id")];
				int id = Integer.parseInt(containerIdString);
				definition.addFieldMapping(field, ContentType.IMAGE, id);
				definition.setMainImageContainerId(id);
				// System.out.println("main image container id " + id);
			} else if (type.equals("table")) {
				System.out.println("parsing table");
				definition.getTableDefinition().setTableFields(field.split(","));
				String containerIdString = record[getFieldIndex(columnNames, "container_id")];
				int id = Integer.parseInt(containerIdString);
				System.out.println("parsing table id: " + id);
				definition.getTableDefinition().setTableContainerId(id);
			} else if (type.equals("pauseTime")) {
				definition.setGlobalImagePauseTime(Integer.parseInt(format));
			} else if (type.equals("batchSize")) {
				definition.setNumberOfRecordsToPlayPerCycle(Integer.parseInt(format));
			} else if (type.equals("tableNumberOfRows")) {
				definition.getTableDefinition().setNumberOfTableRows(Integer.parseInt(format));
			} else if (type.equals("tableRowHeight")) {
				definition.getTableDefinition().setTableRowHeight(Integer.parseInt(format));
			} else {
				throw new InvalidInventoryDataException("invalid type");
			}
		} catch (Exception ex) {
			System.out.println(Arrays.toString(columnNames));
			ex.printStackTrace();
			
			String classMethod = "model.inventory.InventoryDefinitionBuilder in applySetting()";
			LoggingUtils.logStart(classMethod);
			LoggingUtils.log(Level.SEVERE,ex.getMessage() + classMethod,ex);
		}
	}

	private int getFieldColumnIndex(String[] columnNames) {
		return getFieldIndex(columnNames, "field");
	}

	private int getFieldIndex(String[] columnNames, String fieldName) {
		for (int i = 0; i < columnNames.length; i++) {
			if (columnNames[i].equalsIgnoreCase(fieldName)) {
				return i;
			}
		}
		throw new InvalidInventoryDataException("There is no field called '" + fieldName + "'");
	}
}
